﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Assets.Scripts.Pooling
{
    /// <summary>
    /// 一个普通的对象池
    /// </summary>
    /// <typeparam name="E"></typeparam>
    public class ListPooling<E> : IPooling<E>
    {
        public List<E> Pooling { get; protected set; }

        /// <summary>
        /// 什么条件下这个对象是可用的
        /// </summary>
        public Func<E, bool> CanUse;
        /// <summary>
        /// 设置为 被占用 的方法
        /// </summary>
        public Action<E> SetUsed;
        /// <summary>
        /// 设置为 可用 的方法
        /// </summary>
        public Action<E> SetUnused;
        /// <summary>
        /// 如果池子内对象不过，我应该用什么方法创建对象
        /// </summary>
        public Func<E> Generator;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="canUse">什么条件下这个对象是可用的</param>
        /// <param name="setUsed">设置为 被占用 的方法</param>
        /// <param name="setUnused">设置为 可用 的方法</param>
        /// <param name="generator">如果池子内对象不过，我应该用什么方法创建对象</param>
        public ListPooling(Func<E, bool> canUse,Action<E> setUsed,Action<E> setUnused, Func<E> generator)
        {
            Pooling = new List<E>();

            this.CanUse = canUse;
            this.SetUsed = setUsed;
            this.SetUnused = setUnused;
            this.Generator = generator;
        }

        public E GetSpawn()
        {
            E ret = default(E);

            foreach (var item in Pooling)
            {
                if (CanUse(item))
                {
                    ret = item;
                    SetUsed(ret);
                    return ret;
                }
            }

            E e = Generator();
            SetUsed(e);
            Pooling.Add(e);
            return e;
        }

        public void RecycelSpawn(E e)
        {
            SetUnused(e);
        }

        public void RecycleAllSpawn()
        {
            foreach (var item in Pooling)
            {
                SetUnused(item);
            }
        }

        public void EmptyPooling()
        {
            Pooling.Clear();
        }
    }
}
